#include "fs_algo.h"
#include "stl_includes.h"
#include <iomanip>

#define ALL 0
#define MAX_CLASS_NUM 100

typedef pair<int,int> Span;

struct NE
{
	Span sp;
	string tag;
};

map<Span,string> reference[MAX_CLASS_NUM];
map<Span,string> result[MAX_CLASS_NUM];

vector<string> classes;

bool only_boundary = false;

string corpus_A;
string corpus_B;

void read_file(const char* path, map<Span,string> ne_corpus[], string& corpus)
{
	ifstream ifs(path);
	string line;
	int idx = -1;

	while(getline(ifs,line))
	{
		istringstream iss(line);
		string word;
		NE ne;
		
		// [PER Linfeng Song ]
		while(iss >> word)
		{
			if(word[0] == '[')
			{
				ne.tag = word.substr(1,word.length());
				ne.sp.first = idx+1;
			}
			else if(word[0] == ']')
			{
				ne.sp.second = idx;
				ne_corpus[ALL].insert(make_pair(ne.sp,ne.tag));

				for(int i=0; i<(int)classes.size(); i++)
					if(ne.tag == classes[i])
						ne_corpus[i+1].insert(make_pair(ne.sp,ne.tag));
			}
			else
			{
				idx += word.size();
				corpus.insert(corpus.end(),word.begin(),word.end());
			}
		}
	}

	cout << idx << endl;
}

void match( const map<Span,string>& res_corpus, 
		    const map<Span,string>& ref_corpus, 
			const string& type )
{
	int matched = 0, ref_total = ref_corpus.size(), res_total = res_corpus.size();

	for( map<Span,string>::const_iterator cit = res_corpus.begin();
		 cit != res_corpus.end();
		 cit ++ )
	{
		map<Span,string>::const_iterator cit_rhs = ref_corpus.find(cit->first);
		if( cit_rhs != ref_corpus.end())
			if(only_boundary == true || cit_rhs->second == cit->second)
				matched++;
	}

	double p,r,f;

	if(res_total != 0) p = (double)matched/res_total;
	else p = 1;

	if(ref_total != 0) r = (double)matched/ref_total;
	else r = 1;

	if(p+r == 0) f = 0;
	else f = (2*p*r)/(p+r);

	cout << type  << "  " 
		 << setiosflags(ios::fixed) << setprecision(2)
		 << "P: " << 100*p << "  "
		 << "R: " << 100*r << "  "
		 << "F: " << 100*f << endl;
}

void read_classes(const char* path)
{
	classes.clear();

	ifstream ifs(path);
	string line;

	while(getline(ifs,line))
	{
		line = fs_algo::strip(line);

		if(line.empty()) 
			continue;

		classes.push_back(line);
	}
}

int main(int argc, char** argv)
{
	if(argc != 5)
	{
		cerr << "Usage : ./this NE-classes rst-file ref-file only-boundary" << endl;
		exit(1);
	}

	read_classes(argv[1]);
	read_file(argv[2],result,corpus_A);
	read_file(argv[3],reference,corpus_B);

/*
	for(int i=0; i<(int)corpus_A.size()&&i<(int)corpus_B.size(); i++)
	{
		if(corpus_A[i] != corpus_B[i])
		{
			cout << i << endl;
			cout << corpus_A[i] << endl;
			cout << corpus_B[i] << endl << endl;
		}
	}
*/

	if(strcmp(argv[4],"true")==0)
		only_boundary = true;

	match(result[ALL],reference[ALL],"ALL");
	for(int i=0; i<(int)classes.size(); i++)
		match(result[i+1],reference[i+1],classes[i]);

	return 0;
}